package com.quality.web.server.remote.query;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import com.quality.web.server.db.DaoUtil;
import com.quality.web.server.misc.JSONComposer;

public abstract class RemoteQueryServlet extends HttpServlet {

  private static final long serialVersionUID = 1608255933029281149L;

  public abstract String doQuery(QueryParameters queryParameters,
      HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException, SQLException;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    this.doPost(req, resp);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    QueryParameters queryParameters = getQueryParameters(req);
    PrintWriter writer = resp.getWriter();
    try {
      String jsonOut = doQuery(queryParameters, req, resp);
      writer.println(jsonOut);
    } catch (SQLException e) {
      writer.println(JSONComposer.composeError(e));
    } finally {
      DaoUtil.endTransaction();
      writer.close();
    }
  }

  protected QueryParameters getQueryParameters(HttpServletRequest req) {
    String sStart = req.getParameter("start");
    Integer start = null;
    if (sStart != null) {
      try {
        start = Integer.parseInt(sStart);
      } catch (NumberFormatException e) {
      }
    }
    Integer numberToReturn = null;
    String limit = req.getParameter("limit");
    if (limit != null) {
      try {
        numberToReturn = Integer.parseInt(limit);
      } catch (NumberFormatException e) {
      }
    }
    String sortBy = req.getParameter("sort") == null ? "id" : req.getParameter(
        "sort").trim();
    String sortOrder = req.getParameter("dir") == null ? "asc"
        : req.getParameter("dir");
    String query = req.getParameter("query");
    if (query != null) {
      if (query.equals("<<ALL>>")) {
        query = null;
      }
    }

    String filterCol = req.getParameter("filterCol") == null ? ""
        : req.getParameter("filterCol");
    return new QueryParameters(start, numberToReturn, sortBy, sortOrder, query,
        filterCol);
  }

  @SuppressWarnings("unchecked")
  protected void printParameters(HttpServletRequest req) {
    Enumeration<String> parameterNames = req.getParameterNames();

    System.out.println(this.getClass() + "\nRequest Parameters:");
    while (parameterNames.hasMoreElements()) {
      String parameterName = parameterNames.nextElement();
      String[] values = req.getParameterValues(parameterName);
      if (values.length <= 1) {
        System.out.println(" " + parameterName + "="
            + req.getParameter(parameterName));
      } else {
        StringBuilder val = new StringBuilder();
        for (String value : values) {
          val.append(',');
          val.append(value);
        }
        System.out.println(" " + parameterName + "=" + val);
      }

    }
  }

  protected static class QueryParameters {

    private Integer start;
    private Integer numberToReturn;
    private String sortBy;
    private String sortOrder;
    private String query;
    private String filterCol;

    public QueryParameters(Integer start, Integer numberToReturn,
        String sortBy, String sortOrder, String query, String filterCol) {
      super();
      this.start = start;
      this.numberToReturn = numberToReturn;
      this.sortBy = sortBy;
      this.sortOrder = sortOrder;
      this.query = query;
      this.filterCol = filterCol;
    }

    public Integer getStart() {
      return start;
    }

    public Integer getNumberToReturn() {
      return numberToReturn;
    }

    public String getSortBy() {
      return sortBy;
    }

    public String getSortOrder() {
      return sortOrder;
    }

    public String getQuery() {
      return query;
    }

    public String getFilterCol() {
      return filterCol;
    }
  }
}
